home *** CD-ROM | disk | FTP | other *** search
/ Amiga Mag HDD Backup / Amiga Mag HDD Backup.zip / Amiga Mag HDD Backup / Alexander.img.bin / Alexander.img / tech 4.1 editorial Archive.sit / Griebling / Listing2 < prev    next >
Text File  |  1993-06-16  |  9KB  |  336 lines

  1. MODULE Calculator;
  2.  
  3. FROM Conversions IMPORT ConvStrToNum;
  4. FROM ExNumbers   IMPORT ExNumType, StrToExNum, Ex0, Ex1, pi,
  5.                         e, ExNumb, ExToLongCard, ExDiv, ExMult,
  6.                         ExAdd, ExSub, ExCompare, ExCompareType,
  7.                         ExTrunc, ExChgSign, ExStatus,
  8.                         SetMaxDigits, ExStatusType, ExNumToStr;
  9. FROM InOut       IMPORT WriteString, WriteLn, WriteLongCard;
  10. FROM InOutExt    IMPORT ReadLine;
  11. FROM Strings     IMPORT DeleteSubStr, LocateChar, AssignStr,
  12.                         LocateSubStr, ExtractSubStr, LengthStr;
  13. FROM SYSTEM      IMPORT STRPTR, ADR;
  14.  
  15.  
  16. TYPE
  17.   Tokens  = (Empty,
  18.  
  19.              (* expression tokens *)
  20.              Plus, Minus, Or, Xor, StoreMem,
  21.  
  22.              (* term tokens *)
  23.              Times, Divide, ShiftLeft, And, Mod, Div,
  24.              ClearBit, SetBit, ToggleBit, AShiftRight,
  25.              RotateRight, RotateLeft, ShiftRight,
  26.  
  27.              (* power tokens *)
  28.              Power, PercentOf, Root, Squared, Cubed,
  29.              Inverse, Factorial,
  30.  
  31.              (* miscellaneous tokens *)
  32.              LeftBrace, RightBrace, PowerOfe, Sin, Cos,
  33.              Tan, ArcSin, ArcCos, ArcTan, Sinh, Cosh, Tanh,
  34.              ArcSinh, ArcCosh, ArcTanh, Not, Base, Digits,
  35.              Pi, NaturalLog, SquareRoot, CubeRoot, Decimals,
  36.              Notation, Complement, Log, Number, DegRadGrad,
  37.              MemoryCell);
  38.  
  39.  
  40. CONST
  41.   StrSize          = 250;
  42.   Space            = " ";
  43.   NumberChars      = "+-E.0123456789ABCDEF";
  44.   MemoryChars      = "0123456789";
  45.   PunctuationChars = ",'_";
  46.  
  47. TYPE
  48.   String = ARRAY [0..StrSize] OF CHAR;
  49.  
  50. VAR
  51.   Token         : Tokens;
  52.   DecPoint      : CARDINAL;
  53.   SciNotation   : BOOLEAN;
  54.   NumberValue   : ExNumType;
  55.   Answer        : ExNumType;
  56.   ResultStr,
  57.   CommandLine   : String;
  58.  
  59.  
  60. (*$S-*)
  61. PROCEDURE UnsignInt (Number     : ARRAY OF CHAR;
  62.                      VAR Result : ExNumType);
  63. VAR
  64.   numb  : ExNumType;
  65.   done  : BOOLEAN;
  66. BEGIN
  67.   (* perform the actual conversion from string to number *)
  68.   StrToExNum(Number, numb);
  69.   done := ExStatus = Okay;
  70.   IF done THEN  (* all went OK *)
  71.     Result := numb;
  72.   ELSE
  73.     ExStatus := IllegalNumber;
  74.     Result := Ex0;
  75.   END;
  76. END UnsignInt;
  77.  
  78.  
  79. PROCEDURE ExtractNumber(VAR arg         : ARRAY OF CHAR;
  80.                         VAR NumberValue : ExNumType);
  81. VAR
  82.   Constant : String;
  83.   NumChars : ARRAY [0..200] OF CHAR;
  84.   ConIndex : CARDINAL;
  85.  
  86.   PROCEDURE GetNumber();
  87.   BEGIN
  88.     LOOP
  89.       (* gather number characters *)
  90.       IF LocateChar(NumChars, arg[0], 0) # -1 THEN
  91.         (* not punctuation character *)
  92.         Constant[ConIndex] := arg[0];
  93.         INC(ConIndex);
  94.         DeleteSubStr(arg, 0, 1);
  95.       ELSIF LocateChar(PunctuationChars, arg[0], 0) # -1 THEN
  96.         DeleteSubStr(arg, 0, 1);
  97.       ELSE
  98.         EXIT;
  99.       END;
  100.       IF arg[0] = 0C THEN EXIT END;
  101.     END;
  102.   END GetNumber;
  103.  
  104. BEGIN
  105.   Constant := "";
  106.   ConIndex := 0;
  107.  
  108.   (* valid number characters *)
  109.   ExtractSubStr(NumberChars, 0, 14, NumChars);
  110.  
  111.   (* get a number string from the input *)
  112.   GetNumber();
  113.   Constant[ConIndex] := 0C;  (* terminate the new string *)
  114.  
  115.   (* convert to an ExNumber *)
  116.   IF ConIndex > 0 THEN
  117.     UnsignInt(Constant, NumberValue);
  118.   ELSE
  119.     NumberValue := Ex0;
  120.     ExStatus := IllegalNumber; (* illegal number or constant *)
  121.   END;
  122. END ExtractNumber;
  123.  
  124.  
  125. PROCEDURE GetToken(VAR arg : ARRAY OF CHAR);
  126.  
  127. CONST
  128.   Sqrd = "\xB2";
  129.   Tims = "\xD7";
  130.   Divd = "\xF7";
  131.   Min1 = "\xAD\xB9";
  132.  
  133.   PROCEDURE IsToken(Str : ARRAY OF CHAR;
  134.                     T   : Tokens) : BOOLEAN;
  135.   BEGIN
  136.     IF LocateSubStr(arg, Str, 0) = 0 THEN
  137.       DeleteSubStr(arg, 0, LengthStr(Str));
  138.       Token := T;
  139.       RETURN TRUE;
  140.     END;
  141.     RETURN FALSE;
  142.   END IsToken;
  143.  
  144. BEGIN
  145.   (* delete any blank spaces *)
  146.   WHILE arg[0] = Space DO DeleteSubStr(arg, 0, 1); END;
  147.  
  148.   (* form a token *)
  149.   IF ((arg[0] >= "0") & (arg[0] <= "9")) OR (arg[0] = ".") THEN
  150.     (* token is some sort of number *)
  151.     Token := Number;
  152.     ExtractNumber(arg, NumberValue);
  153.   ELSIF arg[0] = 0C THEN
  154.     (* empty string *)
  155.     Token := Empty;
  156.   ELSE
  157.     (* token is a symbol *)
  158.     IF IsToken("+",     Plus)        THEN RETURN END;
  159.     IF IsToken("-",     Minus)       THEN RETURN END;
  160.     IF IsToken(Sqrd,    Squared)     THEN RETURN END;
  161.     IF IsToken("x",     Times)       THEN RETURN END;
  162.     IF IsToken(Tims,    Times)       THEN RETURN END;
  163.     IF IsToken("*",     Times)       THEN RETURN END;
  164.     IF IsToken("/",     Divide)      THEN RETURN END;
  165.     IF IsToken(Divd,    Divide)      THEN RETURN END;
  166.     IF IsToken("(",     LeftBrace)   THEN RETURN END;
  167.     IF IsToken(")",     RightBrace)  THEN RETURN END;
  168.     IF IsToken(Min1,    Inverse)     THEN RETURN END;
  169.     IF IsToken("Pi",    Number)      THEN NumberValue := pi;
  170.                                           RETURN END;
  171.     IF IsToken("SCI",   Notation)    THEN RETURN END;
  172.     IF IsToken("DP",    Decimals)    THEN RETURN END;
  173.     IF IsToken("DIG",   Digits)      THEN RETURN END;
  174.  
  175.     (* Illegal token if we reach here *)
  176.     ExStatus := IllegalOperator;
  177.     DeleteSubStr(arg, 0, 1);
  178.   END;
  179. END GetToken;
  180.  
  181.  
  182. PROCEDURE Expression (VAR arg : ARRAY OF CHAR;
  183.                       VAR Result : ExNumType);
  184.   FORWARD;
  185.  
  186.  
  187. PROCEDURE Factor (VAR arg : ARRAY OF CHAR;
  188.                   VAR Result : ExNumType);
  189. BEGIN
  190.   CASE Token OF
  191.     LeftBrace :
  192.       GetToken(arg);
  193.       Expression(arg, Result);
  194.       IF Token = RightBrace THEN
  195.         GetToken(arg);
  196.       ELSE
  197.         ExStatus := MismatchBraces;
  198.       END;
  199.       |
  200.     Number :
  201.       GetToken(arg);
  202.       Result := NumberValue;
  203.       |
  204.     Digits :
  205.       GetToken(arg);
  206.       Factor(arg, Result);
  207.       SetMaxDigits(ExToLongCard(Result));
  208.       |
  209.     Decimals :
  210.       GetToken(arg);
  211.       Factor(arg, Result);
  212.       DecPoint := ExToLongCard(Result);
  213.       |
  214.     Notation :
  215.       GetToken(arg);
  216.       SciNotation := NOT SciNotation;
  217.       Result := Ex0;
  218.       |
  219.     ELSE
  220.       ExStatus := IllegalOperator;  (* an illegal factor *)
  221.       Result := Ex0;
  222.   END;
  223. END Factor;
  224.  
  225.  
  226. PROCEDURE Powers (VAR arg : ARRAY OF CHAR;
  227.                   VAR Result : ExNumType);
  228. VAR
  229.   temp : ExNumType;
  230. BEGIN
  231.   Factor(arg, temp);
  232.   WHILE (Token >= Power) & (Token <= Factorial) DO
  233.     CASE Token OF
  234.       Squared   : GetToken(arg);
  235.                   ExMult(temp, temp, temp);
  236.                   |
  237.       Inverse   : GetToken(arg);
  238.                   ExDiv(temp, Ex1, temp);
  239.                   |
  240.       ELSE (* do nothing *)
  241.     END;
  242.   END;
  243.   Result := temp;
  244. END Powers;
  245.  
  246.  
  247. PROCEDURE Term (VAR arg : ARRAY OF CHAR;
  248.                 VAR Result : ExNumType);
  249. VAR
  250.   temp, temp2 : ExNumType;
  251. BEGIN
  252.   Powers(arg, temp);
  253.   WHILE (Token >= Times) & (Token <= ShiftRight) DO
  254.     CASE Token OF
  255.       Times  : GetToken(arg);
  256.                Powers(arg, Result);
  257.                ExMult(temp, Result, temp);
  258.                |
  259.       Divide : GetToken(arg);
  260.                Powers(arg, Result);
  261.                ExDiv(temp, temp, Result);
  262.                |
  263.       ELSE (* do nothing *)
  264.     END;
  265.   END;
  266.   Result := temp;
  267. END Term;
  268.  
  269.  
  270. PROCEDURE Expression (VAR arg : ARRAY OF CHAR;
  271.                       VAR Result : ExNumType);
  272. VAR
  273.   temp : ExNumType;
  274.   Str  : String;
  275. BEGIN
  276.   CASE Token OF
  277.     Plus  : GetToken(arg);
  278.             Term(arg, temp);
  279.             |
  280.     Minus : GetToken(arg);
  281.             Term(arg, temp);
  282.             ExChgSign(temp);
  283.             |
  284.     ELSE    Term(arg, temp)
  285.   END;
  286.   WHILE (Token >= Plus) & (Token <= StoreMem) DO
  287.     CASE Token OF
  288.       Plus  : GetToken(arg);
  289.               Term(arg, Result);
  290.               ExAdd(temp, temp, Result);
  291.               |
  292.       Minus : GetToken(arg);
  293.               Term(arg, Result);
  294.               ExSub(temp, temp, Result);
  295.               |
  296.       ELSE    Term(arg, temp);
  297.     END;
  298.   END;
  299.   Result := temp;
  300. END Expression;
  301.  
  302.  
  303. PROCEDURE SimpleExpression (VAR arg    : ARRAY OF CHAR;
  304.                             VAR Result : ExNumType);
  305. BEGIN
  306.   ExStatus := Okay;  (* clear out any previous errors       *)
  307.   GetToken(arg);   (* start things off with the first token *)
  308.   Expression(arg, Result);
  309. END SimpleExpression;
  310.  
  311.  
  312. BEGIN
  313.   Token := Empty;
  314.   DecPoint := 0;
  315.   SciNotation := FALSE;
  316.   LOOP
  317.     WriteString("Calc> ");
  318.     ReadLine(CommandLine);
  319.     IF LengthStr(CommandLine) = 0 THEN
  320.       EXIT;
  321.     END;
  322.     SimpleExpression(CommandLine, Answer);
  323.     IF SciNotation THEN
  324.       ExNumToStr(Answer, DecPoint, 1, ResultStr);
  325.     ELSE
  326.       ExNumToStr(Answer, DecPoint, 0, ResultStr);
  327.     END;
  328.     IF ExStatus = Okay THEN
  329.       WriteString(ResultStr);
  330.     ELSE
  331.       WriteString("Illegal input string!");
  332.     END;
  333.     WriteLn;
  334.   END;
  335. END Calculator.
  336.